Skip to content

feat(mount-provider): implement IPartialMountProvider - #2378

Merged
cristianscheid merged 4 commits into
masterfrom
feat/2308/partial-mount-provider
May 18, 2026
Merged

cristianscheid merged 4 commits into
masterfrom
feat/2308/partial-mount-provider

Conversation

@cristianscheid

@cristianscheid cristianscheid commented Feb 27, 2026 •

Copy link
Copy Markdown
Member

Summary

Implemented IPartialMountProvider in CircleMountProvider by adding getMountsForPath() and added limitToMountpoint() to CoreQueryBuilder to support filtering.

Testing

I couldn't fully test this because the code path isn't triggered without changes to lib/AppInfo/Application::registerMountProvider() and lib/FederatedItems/Files/FileShare::manage(). That said, I was able to check the behavior using step debugging as follows:

  • Temporarily commented out the if (!$this->configService->isLocalInstance($event->getOrigin())) condition in lib/FederatedItems/Files/FileShare::manage() to allow mount entries to be created locally
  • Created teams mock_team_1, mock_team_2 and mock_team_3
  • Created folders mock_folder_1, mock_folder_2 and mock_folder_3 and shared with their respective teams (mock_team_1, mock_team_2 and mock_team_3)
  • Temporarily commented out the early return in lib/AppInfo/Application::registerMountProvider() to force registration of CircleMountProvider regardless of GlobalScale availability
  • Using Xdebug with a breakpoint on circles/lib/MountManager/CircleMountProvider::getMountsForUser(), accessed nextcloud.local/index.php/apps/dashboard/, triggering the getMountsForUser() method
  • Instead of running the regular method flow, I created some mock params and called getMountsForPath() directly:
$makeMountArg = function(string $path) use ($user): \OCP\Files\Config\MountProviderArgs {
	$mountInfo = new class($user, $path) implements \OCP\Files\Config\ICachedMountInfo {
		public function __construct(private \OCP\IUser $user, private string $path) {}
		public function getUser(): \OCP\IUser { return $this->user; }
		public function getMountPoint(): string { return '/' . $this->user->getUID() . '/files/' . $this->path; }
		public function getStorageId(): int { return 0; }
		public function getRootId(): int { return 0; }
		public function getMountPointNode(): ?\OCP\Files\Node { return null; }
		public function getMountId(): ?int { return null; }
		public function getRootInternalPath(): string { return ''; }
		public function getMountProvider(): string { return ''; }
		public function getKey(): string { return ''; }
	};
	return new \OCP\Files\Config\MountProviderArgs(
		$mountInfo,
		new \OC\Files\Cache\CacheEntry([])
	);
};

$this->getMountsForPath(
	'/' . $user->getUID() . '/files/mock_folder',
	false,
	[
		$makeMountArg('mock_folder_1'),
		$makeMountArg('mock_folder_2'),
		$makeMountArg('another_folder'),
	],
	$loader
);

Results

  • Path filtering worked correctly when forChildren was set to false. With multiple folders on my setup (mock_team_1, mock_team_2 and mock_team_3), in the test above only the requested mounts that exist in the DB were returned for the given paths when calling getForUser() inside getMountsForPath(), confirming that limitToMountpoints() is filtering correctly at the database level.
  • forChildren did not work as expected when set to true. During testing, circles always stored mountpoints relatively. For example, sharing a folder created inside mock_folder generated a circles_mount entry with mountpoint /mock_subfolder instead of /mock_folder/mock_subfolder. As a result, the LIKE '/mock_folder/%' filter used when forChildren is true will not match these entries.
  • During testing, generateCircleMount() threw an exception in both the original getMountsForUser() and on new method getMountsForPath(). I believe this happened because the mount entries were artificially created by bypassing the remote instance check in FileShare::manage(), resulting in incomplete data compared to what would be present in a real GlobalScale environment.

Checklist

AI (if applicable)

  • The content of this PR was partly or fully generated using AI

Comment thread lib/MountManager/CircleMountProvider.php Outdated
Comment thread lib/MountManager/CircleMountProvider.php Outdated
@cristianscheid

Copy link
Copy Markdown
Member Author

@provokateurin I've addressed your review comments and updated the PR description with new testing instructions. Thanks!

Comment thread lib/Db/CoreQueryBuilder.php Outdated
Comment thread lib/Db/CoreQueryBuilder.php
Comment thread lib/Db/CoreQueryBuilder.php Outdated
Comment thread lib/Db/MountRequest.php Outdated
Comment thread lib/MountManager/CircleMountProvider.php Outdated
Comment thread lib/MountManager/CircleMountProvider.php
Comment thread lib/MountManager/CircleMountProvider.php Outdated
@cristianscheid
cristianscheid force-pushed the feat/2308/partial-mount-provider branch from a1632ed to ce45026 Compare April 2, 2026 18:53
@cristianscheid

Copy link
Copy Markdown
Member Author

@provokateurin @salmart-dev I've adjusted the PR after your suggestions. Would appreciate another review when you have a chance.

@cristianscheid

Copy link
Copy Markdown
Member Author

@provokateurin @salmart-dev I've adjusted the PR after your suggestions. Would appreciate another review when you have a chance.

@provokateurin @salmart-dev ping

@provokateurin provokateurin left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, just one small change needed.

Comment thread lib/Db/CoreQueryBuilder.php Outdated
Comment thread lib/Db/MountRequest.php Outdated
Signed-off-by: Cristian Scheid <cristianscheid@gmail.com>
…single query

Signed-off-by: Cristian Scheid <cristianscheid@gmail.com>
…s function

Signed-off-by: Cristian Scheid <cristianscheid@gmail.com>
Signed-off-by: Cristian Scheid <cristianscheid@gmail.com>
@cristianscheid
cristianscheid force-pushed the feat/2308/partial-mount-provider branch from f82630b to 523499a Compare April 27, 2026 22:22
@cristianscheid

Copy link
Copy Markdown
Member Author

Let's wait to merge this PR, I want to make another round of testitng to check things are working as expected.

@provokateurin
provokateurin marked this pull request as draft May 11, 2026 07:09
@cristianscheid

cristianscheid commented May 11, 2026 •

Copy link
Copy Markdown
Member Author

I set up a globalscale env with 1 master + 2 slaves + lookup server to check how circles currently generates mountpoints.

slave 1 instance - haze-pivotal-hagfish
slave 2 instance - haze-amusing-sparrow

On haze-pivotal-hagfish:

  • created team_pivotal and added user_amusing from slave 2
  • created the following folders:
    • folder_pivotal
    • subfolder_inside_folder_pivotal (inside folder_pivotal)
    • subfolder_inside_non_shared_folder (inside another non shared folder)
  • shared folders with team_pivotal

That generated the following entries on haze-amusing-sparrow:

oc_circles_mount:

id mount_id circle_id single_id token parent mountpoint mountpoint_hash remote remote_id
7 g46HWdASBq8xbjb I6CdafCDCzY8AKO13e6sAoWSZg6mn1R 5ZdOTnMV8xesk5SHuKtscj34ff9FcOc -1 /folder_pivotal 5a7eef2bd259fc6586b62667027b0489 pivotal-hagfish.haze.192.168.0.4.sslip.io 11
8 ZCvszk4KDM13Wuh I6CdafCDCzY8AKO13e6sAoWSZg6mn1R 5ZdOTnMV8xesk5SHuKtscj34ff9FcOc -1 /subfolder_inside_folder_pivotal f443cd8d21106a8f7c85df39151c2428 pivotal-hagfish.haze.192.168.0.4.sslip.io 12
9 UyMPhpZwfwBbm8l I6CdafCDCzY8AKO13e6sAoWSZg6mn1R 5ZdOTnMV8xesk5SHuKtscj34ff9FcOc -1 /subfolder_inside_non_shared_folder 99d80bdf93dd5fe5e7477b2ed5ec888e pivotal-hagfish.haze.192.168.0.4.sslip.io 13

oc_circles_mountpoint:

single_id on this table = single_id from oc_cicles_membership and oc_circle_member

id mount_id single_id mountpoint mountpoint_hash
7 g46HWdASBq8xbjb T549kxw7Ax1iwKTH4VY2pJNqwxjZoHe /folder_pivotal 5a7eef2bd259fc6586b62667027b0489
8 ZCvszk4KDM13Wuh T549kxw7Ax1iwKTH4VY2pJNqwxjZoHe /subfolder_inside_folder_pivotal f443cd8d21106a8f7c85df39151c2428
9 UyMPhpZwfwBbm8l T549kxw7Ax1iwKTH4VY2pJNqwxjZoHe /subfolder_inside_non_shared_folder 99d80bdf93dd5fe5e7477b2ed5ec888e

As seen above, circles stores mountpoints relatively, without any parent-child relationship in the database. Given that, the LIKE '/folder_pivotal/_%' query in limitToMountpoints would never match /subfolder_inside_folder_pivotal, since the stored mountpoint does not include the parent path. So it seems to me that the forChildren in limitToMountpoints would never return the expected results. Does that make sense to you?

cc @provokateurin

@provokateurin

Copy link
Copy Markdown
Member

I agree that this seems to not work then, which is quite confusing. Please check how the full mountpoint is assembled for the folders and replicate it such that the query will match.

Given the difficulties, it would be great if you could create a test for this.

@cristianscheid

cristianscheid commented May 14, 2026 •

Copy link
Copy Markdown
Member Author

I agree that this seems to not work then, which is quite confusing. Please check how the full mountpoint is assembled for the folders and replicate it such that the query will match.

You mean to check how the mountpoints are generated on the oc_mounts table? I spent some time trying to set up a GlobalScale environment to investigate this:

  • 1 master + 2 slaves + lookup server
    • slave 1: haze-particular-trumpeter
      • created user admin_particular
    • slave 2: haze-outspoken-greenfinch
      • created user admin_outspoken
    • the global scale seems to work as expected, as if I'm not logged it redirects me to the master, and after login I'm redirected to the corresponding slave instance
  • setup trusted servers on both slaves pointing to each other (both verified with check signal)
  • enabled federated teams and added frontal URL on both slaves
  • ran occ circles:remote on both slaves: output shows one entry for each one pointing to each other instance and type External
cristian@tuxedo:~/Dev/haze$ haze haze-particular-trumpeter occ circles:remote
+------------------------------------------------+----------+---------+--------------------+--------------------+---------+
| Instance                                       | Type     | iface   | UID                | Authed             | Aliases |
+------------------------------------------------+----------+---------+--------------------+--------------------+---------+
| outspoken-greenfinch.haze.192.168.0.4.sslip.io | External | frontal | a0c388d0b30be62ed0 | a0c388d0b30be62ed0 | []      |
+------------------------------------------------+----------+---------+--------------------+--------------------+---------+
cristian@tuxedo:~/Dev/haze$ haze haze-outspoken-greenfinch occ circles:remote
+------------------------------------------------+----------+---------+--------------------+--------------------+---------+
| Instance                                       | Type     | iface   | UID                | Authed             | Aliases |
+------------------------------------------------+----------+---------+--------------------+--------------------+---------+
| particular-trumpeter.haze.192.168.0.4.sslip.io | External | frontal | 1aebf1ffb540f8084a | 1aebf1ffb540f8084a | []      |
+------------------------------------------------+----------+---------+--------------------+--------------------+---------+
  • created team_outspoken on slave 2
  • added admin_particular from slave 1 on slave 2's team like this:
occ circles:members:add --type 1 <circle_id> admin_particular@particular-trumpeter.haze.192.168.0.4.sslip.io
// --type 1 represents circles/lib/Model/Member const TYPE_USER = 1
  • on slave 2, shared folder with slave 2's team

Entries were generated on oc_circles_mount and oc_circles_mountpoint on slave 1, but no entries appeared on oc_mounts. When trying to access the files page on slave 1 (with admin_particular user), I ran into the following exceptions:

{
  "reqId": "gw45DAMrZbsKbl76fcc0",
  "level": 2,
  "time": "2026-05-14T11:45:52+00:00",
  "remoteAddr": "172.19.0.1",
  "user": "admin_particular",
  "app": "PHP",
  "method": "GET",
  "url": "/index.php/apps/files/",
  "scriptName": "/index.php",
  "message": "Undefined array key \"manager\" at /var/www/html/apps/files_sharing/lib/External/Storage.php#62",
  "userAgent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36",
  "version": "34.0.0.6",
  "data": {
    "app": "PHP"
  }
}
{
  "reqId": "gw45DAMrZbsKbl76fcc0",
  "level": 3,
  "time": "2026-05-14T11:45:52+00:00",
  "remoteAddr": "172.19.0.1",
  "user": "admin_particular",
  "app": "index",
  "method": "GET",
  "url": "/index.php/apps/files/",
  "scriptName": "/index.php",
  "message": "Cannot assign null to property OCA\\Files_Sharing\\External\\Storage::$manager of type OCA\\Files_Sharing\\External\\Manager in file '/var/www/html/apps/files_sharing/lib/External/Storage.php' line 62",
  "userAgent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36",
  "version": "34.0.0.6",
  "exception": {
    "Exception": "Exception",
    "Message": "Cannot assign null to property OCA\\Files_Sharing\\External\\Storage::$manager of type OCA\\Files_Sharing\\External\\Manager in file '/var/www/html/apps/files_sharing/lib/External/Storage.php' line 62",
    "Code": 0,
    "Trace": [
      {
        "file": "/var/www/html/lib/private/AppFramework/App.php",
        "line": 137,
        "function": "dispatch",
        "class": "OC\\AppFramework\\Http\\Dispatcher",
        "type": "->",
        "args": [
          {
            "__class__": "OCA\\Files\\Controller\\ViewController"
          },
          "index"
        ]
      },
      {
        "file": "/var/www/html/lib/private/Route/Router.php",
        "line": 324,
        "function": "main",
        "class": "OC\\AppFramework\\App",
        "type": "::",
        "args": [
          "OCA\\Files\\Controller\\ViewController",
          "index",
          {
            "__class__": "OC\\AppFramework\\DependencyInjection\\DIContainer"
          },
          {
            "_route": "files.view.index"
          }
        ]
      },
      {
        "file": "/var/www/html/lib/base.php",
        "line": 1159,
        "function": "match",
        "class": "OC\\Route\\Router",
        "type": "->",
        "args": [
          "/apps/files/"
        ]
      },
      {
        "file": "/var/www/html/index.php",
        "line": 25,
        "function": "handleRequest",
        "class": "OC",
        "type": "::",
        "args": []
      }
    ],
    "File": "/var/www/html/lib/private/AppFramework/Http/Dispatcher.php",
    "Line": 110,
    "Previous": {
      "Exception": "TypeError",
      "Message": "Cannot assign null to property OCA\\Files_Sharing\\External\\Storage::$manager of type OCA\\Files_Sharing\\External\\Manager",
      "Code": 0,
      "Trace": [
        {
          "file": "/var/www/html/lib/private/Files/Mount/MountPoint.php",
          "line": 129,
          "function": "__construct",
          "class": "OCA\\Files_Sharing\\External\\Storage",
          "type": "->",
          "args": [
            {
              "0": "And 2 more entries, set log level to debug to see all entries",
              "owner": "admin_outspoken",
              "remote": "https://outspoken-greenfinch.haze.192.168.0.4.sslip.io",
              "token": "",
              "password": "",
              "mountpoint": "/admin_particular/files/folder_outspoken"
            }
          ]
        },
        {
          "file": "/var/www/html/lib/private/Files/Mount/MountPoint.php",
          "line": 155,
          "function": "createStorage",
          "class": "OC\\Files\\Mount\\MountPoint",
          "type": "->",
          "args": [
            "*** sensitive parameters replaced ***"
          ]
        },
        {
          "file": "/var/www/html/lib/private/Files/Mount/MountPoint.php",
          "line": 263,
          "function": "getStorage",
          "class": "OC\\Files\\Mount\\MountPoint",
          "type": "->",
          "args": []
        },
        {
          "file": "/var/www/html/lib/private/Files/Config/UserMountCache.php",
          "line": 72,
          "function": "getStorageRootId",
          "class": "OC\\Files\\Mount\\MountPoint",
          "type": "->",
          "args": []
        },
        {
          "file": "/var/www/html/lib/private/Files/SetupManager.php",
          "line": 267,
          "function": "registerMounts",
          "class": "OC\\Files\\Config\\UserMountCache",
          "type": "->",
          "args": [
            "*** sensitive parameters replaced ***",
            [
              {
                "__class__": "OCA\\Circles\\MountManager\\CircleMount"
              }
            ],
            {
              "0": "OC\\Files\\Mount\\CacheMountProvider",
              "1": "OCA\\Circles\\MountManager\\CircleMountProvider",
              "3": "OCA\\Files_Sharing\\External\\MountProvider"
            }
          ]
        },
        {
          "file": "/var/www/html/lib/private/Files/SetupManager.php",
          "line": 483,
          "function": "updateNonAuthoritativeProviders",
          "class": "OC\\Files\\SetupManager",
          "type": "->",
          "args": [
            "*** sensitive parameters replaced ***"
          ]
        },
        {
          "file": "/var/www/html/lib/private/Files/Mount/Manager.php",
          "line": 80,
          "function": "setupForPath",
          "class": "OC\\Files\\SetupManager",
          "type": "->",
          "args": [
            "/admin_particular/files"
          ]
        },
        {
          "file": "/var/www/html/lib/private/Files/View.php",
          "line": 1441,
          "function": "find",
          "class": "OC\\Files\\Mount\\Manager",
          "type": "->",
          "args": [
            "/admin_particular/files"
          ]
        },
        {
          "file": "/var/www/html/lib/private/Files/Filesystem.php",
          "line": 649,
          "function": "getFileInfo",
          "class": "OC\\Files\\View",
          "type": "->",
          "args": [
            "/admin_particular/files",
            false
          ]
        },
        {
          "file": "/var/www/html/apps/files/lib/Controller/ViewController.php",
          "line": 79,
          "function": "getFileInfo",
          "class": "OC\\Files\\Filesystem",
          "type": "::",
          "args": [
            "/",
            false
          ]
        },
        {
          "file": "/var/www/html/apps/files/lib/Controller/ViewController.php",
          "line": 172,
          "function": "getStorageInfo",
          "class": "OCA\\Files\\Controller\\ViewController",
          "type": "->",
          "args": [
            "/"
          ]
        },
        {
          "file": "/var/www/html/lib/private/AppFramework/Http/Dispatcher.php",
          "line": 165,
          "function": "index",
          "class": "OCA\\Files\\Controller\\ViewController",
          "type": "->",
          "args": [
            "",
            "",
            null
          ]
        },
        {
          "file": "/var/www/html/lib/private/AppFramework/Http/Dispatcher.php",
          "line": 78,
          "function": "executeController",
          "class": "OC\\AppFramework\\Http\\Dispatcher",
          "type": "->",
          "args": [
            {
              "__class__": "OCA\\Files\\Controller\\ViewController"
            },
            "index"
          ]
        },
        {
          "file": "/var/www/html/lib/private/AppFramework/App.php",
          "line": 137,
          "function": "dispatch",
          "class": "OC\\AppFramework\\Http\\Dispatcher",
          "type": "->",
          "args": [
            {
              "__class__": "OCA\\Files\\Controller\\ViewController"
            },
            "index"
          ]
        },
        {
          "file": "/var/www/html/lib/private/Route/Router.php",
          "line": 324,
          "function": "main",
          "class": "OC\\AppFramework\\App",
          "type": "::",
          "args": [
            "OCA\\Files\\Controller\\ViewController",
            "index",
            {
              "__class__": "OC\\AppFramework\\DependencyInjection\\DIContainer"
            },
            {
              "_route": "files.view.index"
            }
          ]
        },
        {
          "file": "/var/www/html/lib/base.php",
          "line": 1159,
          "function": "match",
          "class": "OC\\Route\\Router",
          "type": "->",
          "args": [
            "/apps/files/"
          ]
        },
        {
          "file": "/var/www/html/index.php",
          "line": 25,
          "function": "handleRequest",
          "class": "OC",
          "type": "::",
          "args": []
        }
      ],
      "File": "/var/www/html/apps/files_sharing/lib/External/Storage.php",
      "Line": 62
    },
    "message": "Cannot assign null to property OCA\\Files_Sharing\\External\\Storage::$manager of type OCA\\Files_Sharing\\External\\Manager in file '/var/www/html/apps/files_sharing/lib/External/Storage.php' line 62",
    "exception": "{\"class\":\"Exception\",\"message\":\"Cannot assign null to property OCA\\Files_Sharing\\External\\Storage::$manager of type OCA\\Files_Sharing\\External\\Manager in file '/var/www/html/apps/files_sharing/lib/External/Storage.php' line 62\",\"code\":0,\"file\":\"/var/www/html/lib/private/AppFramework/Http/Dispatcher.php:110\",\"trace\":\"#0 /var/www/html/lib/private/AppFramework/App.php(137): OC\\AppFramework\\Http\\Dispatcher->dispatch(Object(OCA\\Files\\Controller\\ViewController), 'index')\\n#1 /var/www/html/lib/private/Route/Router.php(324): OC\\AppFramework\\App::main('OCA\\\\Files\\\\Contr...', 'index', Object(OC\\AppFramework\\DependencyInjection\\DIContainer), Array)\\n#2 /var/www/html/lib/base.php(1159): OC\\Route\\Router->match('/apps/files/')\\n#3 /var/www/html/index.php(25): OC::handleRequest()\\n#4 {main}\",\"previous\":{\"class\":\"TypeError\",\"message\":\"Cannot assign null to property OCA\\Files_Sharing\\External\\Storage::$manager of type OCA\\Files_Sharing\\External\\Manager\",\"code\":0,\"file\":\"/var/www/html/apps/files_sharing/lib/External/Storage.php:62\",\"trace\":\"#0 /var/www/html/lib/private/Files/Mount/MountPoint.php(129): OCA\\Files_Sharing\\External\\Storage->__construct(Array)\\n#1 /var/www/html/lib/private/Files/Mount/MountPoint.php(155): OC\\Files\\Mount\\MountPoint->createStorage()\\n#2 /var/www/html/lib/private/Files/Mount/MountPoint.php(263): OC\\Files\\Mount\\MountPoint->getStorage()\\n#3 /var/www/html/lib/private/Files/Config/UserMountCache.php(72): OC\\Files\\Mount\\MountPoint->getStorageRootId()\\n#4 /var/www/html/lib/private/Files/SetupManager.php(267): OC\\Files\\Config\\UserMountCache->registerMounts(Object(OC\\User\\User), Array, Array)\\n#5 /var/www/html/lib/private/Files/SetupManager.php(483): OC\\Files\\SetupManager->updateNonAuthoritativeProviders(Object(OC\\User\\User))\\n#6 /var/www/html/lib/private/Files/Mount/Manager.php(80): OC\\Files\\SetupManager->setupForPath('/admin_particul...')\\n#7 /var/www/html/lib/private/Files/View.php(1441): OC\\Files\\Mount\\Manager->find('/admin_particul...')\\n#8 /var/www/html/lib/private/Files/Filesystem.php(649): OC\\Files\\View->getFileInfo('/admin_particul...', false)\\n#9 /var/www/html/apps/files/lib/Controller/ViewController.php(79): OC\\Files\\Filesystem::getFileInfo('/', false)\\n#10 /var/www/html/apps/files/lib/Controller/ViewController.php(172): OCA\\Files\\Controller\\ViewController->getStorageInfo('/')\\n#11 /var/www/html/lib/private/AppFramework/Http/Dispatcher.php(165): OCA\\Files\\Controller\\ViewController->index('', '', NULL)\\n#12 /var/www/html/lib/private/AppFramework/Http/Dispatcher.php(78): OC\\AppFramework\\Http\\Dispatcher->executeController(Object(OCA\\Files\\Controller\\ViewController), 'index')\\n#13 /var/www/html/lib/private/AppFramework/App.php(137): OC\\AppFramework\\Http\\Dispatcher->dispatch(Object(OCA\\Files\\Controller\\ViewController), 'index')\\n#14 /var/www/html/lib/private/Route/Router.php(324): OC\\AppFramework\\App::main('OCA\\\\Files\\\\Contr...', 'index', Object(OC\\AppFramework\\DependencyInjection\\DIContainer), Array)\\n#15 /var/www/html/lib/base.php(1159): OC\\Route\\Router->match('/apps/files/')\\n#16 /var/www/html/index.php(25): OC::handleRequest()\\n#17 {main}\"}}",
    "CustomMessage": "Cannot assign null to property OCA\\Files_Sharing\\External\\Storage::$manager of type OCA\\Files_Sharing\\External\\Manager in file '/var/www/html/apps/files_sharing/lib/External/Storage.php' line 62"
  }
}

Seems like the manager key is missing on circles/lib/Model/Mount::toMount(), causing the crash before oc_mounts can be populated. I talked to @ArtificialOwl and he mentioned federated teams was a proof of concept from NC22, never officially used until NC33, so some rough edges are expected. I did the same scenario/test as above on master branch and ran into the same problem, so it seems unrelated to this PR.

Since I couldn't get oc_mounts populated, I couldn't directly observe how the full mountpoint is assembled there. However, through step debugging I could spot that lib/private/Files/SetupManager::setupForPath() receives full paths like /admin_particular/files/folder_outspoken. With this, the relative path extracted in getMountsForPath should match exactly what is stored in oc_circles_mountpoint, so the IN query for forChildren=false should work correctly once the other issues are fixed.

So it seems to me that the expected functionality is not yet working and I'm not sure if we should move on with this implementation, or try to fix the situation descbribed above first? Maybe I'm also missing something on the way I setup the environment?

@cristianscheid
cristianscheid marked this pull request as ready for review May 18, 2026 13:46
@cristianscheid

Copy link
Copy Markdown
Member Author

After investigation (details on previous comments) and internal discussion, it was decided to merge this PR for now as it looks in good shape from what was seen during step debugging. Problems faced during population of oc_mounts seem unrelated from this PR, and this implementation can be addressed again if needed once that's fixed.

@cristianscheid
cristianscheid merged commit 6d3e957 into master May 18, 2026
42 checks passed
@cristianscheid
cristianscheid deleted the feat/2308/partial-mount-provider branch May 18, 2026 14:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: Implement the new partial mount provider API

3 participants